package parserxml;

import java.util.*;
import java.util.ArrayList;


public class Tabla {

    private String nombre;
    private HashMap<String,Atributo> atributos;
    private HashSet<String> clavePK;
    private HashMap<String,HashSet <String>> clavesFK;
    private ArrayList<HashMap<String, String>> filas;

  public Tabla(String nombre) {
    this.nombre = nombre;
    this.atributos = new HashMap<String, Atributo>();
    this.filas = new ArrayList<HashMap<String, String>>();
    this.clavePK = new HashSet<String>();
    this.clavesFK = new HashMap<String, HashSet<String>>();

  }

  /**
   * @return the nombre
   */
  public String getNombre() {
    return nombre;
  }

  /**
   * @param nombre the nombre to set
   */
  public void setNombre(String nombre) {
    this.nombre = nombre;
  }

  public boolean hasAtributo(String nombreAtributo) {
    return this.atributos.containsKey(nombreAtributo);
  }

  public void addAtributo(String nombreAtributo, Atributo atributo) {
    this.atributos.put(nombreAtributo, atributo);
  }

  public Atributo getAtributo(String nombreAtributo) {
    return this.atributos.get(nombreAtributo);
  }

  public void removeAtributo(String nombreAtributo) {

    this.atributos.remove(nombreAtributo);

  }

  /**
   * Retorna un iterador de todos los atributos de la tabla
   *
   * @return the atributos
   */
  public Iterator<Atributo> getAllAtributos() {
    return atributos.values().iterator();
  }

  /**
   * @return the clave
   */
  public HashSet<String> getClavePK() {
    return clavePK;
  }

  public HashMap<String, HashSet<String>> getClavesFK() {
    return clavesFK;
  }

  public void setClavePK(HashSet<String> clavePK) {
    this.clavePK = clavePK;
  }

  public void addClavePK(String clave) {
    this.clavePK.add(clave);
  }

  public void addClavesFK(String entidad, HashSet<String> claves) {
    this.clavesFK.put(entidad, claves);
  }

  /**
   * Retorna true si el valor ya esta incluido en la tabla
   * @param valor El valor a chequear
   */
  public boolean hasFila(HashMap<String, String> fila) {
    return filas.contains(fila);
  }

  public HashMap<String, String> getEntidadConClave(String columnaClave, String clave) {
    Iterator<HashMap<String, String>> iteFilas = filas.iterator();
    HashMap<String, String> fila;
    while (iteFilas.hasNext()) {
      fila = iteFilas.next();
      if (fila.get(columnaClave).equals(clave)) {
        return fila;
      }
    }
    return null;
  }

  /**
   * Agrega un nuevo valor en la tabla
   * @param valor El valor a agregar
   */
  public void addFila(HashMap<String, String> filaAgregar) {
//    // chequeo que no falten valores para las columnas clavePK
//    Iterator<String> iteClaves = clavePK.iterator();
//    String clave;
//    while (iteClaves.hasNext()) {
//      clave = iteClaves.next();
//      if (!filaAgregar.containsKey(clave)) {
//        // TODO error, falta una de las claves PK en la fila
//        return;
//      }
//    }
//    // chequeo que se cumpla la restriccion de clave primaria unica
//    Iterator<HashMap<String, String>> iteFilas = filas.iterator();
//    HashMap<String, String> fila;
//    while (iteFilas.hasNext()) {
//      fila = iteFilas.next();
//      iteClaves = clavePK.iterator();
//      while (iteClaves.hasNext()) {
//        clave = iteClaves.next();
//        if (fila.get(clave).equals(filaAgregar.get(clave))) {
//          if (!iteClaves.hasNext()) {
//            // TODO error, la clave primaria no es unica
//            System.err.println(filaAgregar);
//            System.err.println("la clave primaria no es unica");
//            return;
//          }
//        } else {
//          break;
//        }
//      }
//      // si termina el ciclo entonces es porque todas las claves concuerdan
//      // en ambas filas, por lo que la clave primaria compuesta se esta repitiendo
//    }
//    
//    // chequeo que no falten valores para las columnas de atributos requeridos
//    Iterator<Atributo> iteAtributos = atributos.values().iterator();
//    Atributo atributo;
//    while (iteAtributos.hasNext()) {
//      atributo = iteAtributos.next();
//      if (!atributo.getIsNull() && !filaAgregar.containsKey(atributo.getNombre())) {
//        // TODO error, el atributo bla... no puede ser nulo
//        return;
//      }
//    }
    filas.add(filaAgregar);
  }

  public Iterator<HashMap<String, String>> getFilas() {
    return filas.iterator();
  }

  /**
   * @return Retorna un String con todas las claves
   * primarias de la tabla concatenadas con coma.
   */
  public String pkToString() {

    Iterator<String> iterPk = this.clavePK.iterator();
    String claves = new String();

    if (iterPk.hasNext()) {
      claves = iterPk.next();
    }

    while (iterPk.hasNext()) {
      claves += ", " + iterPk;
    }
    return claves;
  }

  /**
   * @return Retorna una LinkedList con todas las claves primarias.
   */
  public LinkedList<Atributo> pkList() {

    LinkedList<Atributo> listaDeClaves = new LinkedList<Atributo>();
    Iterator clavePkIter = this.clavePK.iterator();

    while (clavePkIter.hasNext()) {

      Atributo attr = new Atributo((String) clavePkIter.next(), false);
      listaDeClaves.add(attr);
    }
    return listaDeClaves;
  }

  /**
   * @return Retorna un String con todas las claves
   * foraneas concatenadas con coma.
   */
  public String fkToString() {

        Iterator<String> iteradorClaves = this.clavesFK.keySet().iterator();
        String claves = iteradorClaves.next();

    while (iteradorClaves.hasNext()) {

      claves += ", " + iteradorClaves.next();
    }
    return claves;
  }
}
